package com.example.demo.singletonMode;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

/**
 * 反射破解双检锁单例
 */
public class Reflex {

    private volatile static Reflex REFLEX;

    private static Boolean flag = false;

    private Reflex(){
        synchronized (Reflex.class){
            if(flag == false){
                flag = true;
            }else {
                throw new RuntimeException("不要试图用反射来破解单例");
            }
        }
    }
    private static Reflex getInstance(){
        if(REFLEX == null){
            synchronized (SyncLazy.class){
                if(REFLEX == null){
                    REFLEX = new Reflex();
                }
            }
        }
        return REFLEX;
    }

//    /**
//     * 正常调用类是单例的
//     */
//    public static void main(String[] args) {
//        Reflex instance = Reflex.getInstance();
//        Reflex instance1 = Reflex.getInstance();
//        System.err.println(instance == instance1);
//    }

//    /**
//     * 通过反射破解 -- 构造器内加入判断即可阻止
//     */
//    public static void main(String[] args) throws Exception {
//        Reflex instance = Reflex.getInstance();
//        Constructor<Reflex> declaredConstructor = Reflex.class.getDeclaredConstructor(null);
//        declaredConstructor.setAccessible(true);
//        Reflex instance2 = declaredConstructor.newInstance();
//        System.err.println(instance);
//        System.err.println(instance2);
//    }

//    /**
//     * 实例都用反射来创建 -- 构造器内加入标记可阻止
//     */
//    public static void main(String[] args) throws Exception {
//        Constructor<Reflex> declaredConstructor = Reflex.class.getDeclaredConstructor(null);
//        declaredConstructor.setAccessible(true);
//        Reflex reflex = declaredConstructor.newInstance();
//        Reflex reflex2 = declaredConstructor.newInstance();
//        System.err.println(reflex);
//        System.err.println(reflex2);
//    }

    /**
     * 通过反射来修改标记 ---
     */
    public static void main(String[] args) throws Exception{

        Field flag = Reflex.class.getDeclaredField("flag");
        flag.setAccessible(true);

        Constructor<Reflex> declaredConstructor = Reflex.class.getDeclaredConstructor(null);
        declaredConstructor.setAccessible(true);
        Reflex reflex = declaredConstructor.newInstance();
        flag.set(reflex,false);
        Reflex reflex2 = declaredConstructor.newInstance();
        System.err.println(reflex);
        System.err.println(reflex2);
    }

}
